using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using DropBoxTool;
using Microsoft.Phone.Controls;

namespace DropBoxTool.Model
{
    public partial class ViewModelPageClassWithQuery : PhoneApplicationPage, INotifyPropertyChanged
    {
        private static bool? _isInDesignMode;

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Gets a value indicating whether the control is in design mode
        /// (running in Blend or Visual Studio).
        /// </summary>
        [SuppressMessage(
            "Microsoft.Security",
            "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands",
            Justification = "The security risk here is Negligible.")]
        public static bool IsInDesignModeStatic
        {
            get
            {
                if (!_isInDesignMode.HasValue)
                {
#if SILVERLIGHT
                    _isInDesignMode = DesignerProperties.IsInDesignTool;
#else
		                    var prop = DesignerProperties.IsInDesignModeProperty;
		                    _isInDesignMode
		                        = (bool)DependencyPropertyDescriptor
		                        .FromProperty(prop, typeof(FrameworkElement))
		                        .Metadata.DefaultValue;

		                    // Just to be sure
		                    if (!_isInDesignMode.Value
		                        && Process.GetCurrentProcess().ProcessName.StartsWith("devenv", StringComparison.Ordinal))
		                    {
		                        _isInDesignMode = true;
		                    }
#endif
                }

                return _isInDesignMode.Value;
            }
        }

        /// <summary>
        /// Gets a value indicating whether the control is in design mode
        /// (running under Blend or Visual Studio).
        /// </summary>
        [SuppressMessage(
            "Microsoft.Performance",
            "CA1822:MarkMembersAsStatic",
            Justification = "Non static member needed for data binding")]
        public bool IsInDesignMode
        {
            get
            {
                return IsInDesignModeStatic;
            }
        }

        /// <summary>
        /// Raises the PropertyChanged event if needed, and broadcasts a
        /// PropertyChangedMessage using the Messenger instance (or the
        /// static default instance if no Messenger instance is available).
        /// </summary>
        /// <typeparam name="T">The type of the property that
        /// changed.</typeparam>
        /// <param name="propertyName">The name of the property that
        /// changed.</param>
        /// <param name="oldValue">The property's value before the change
        /// occurred.</param>
        /// <param name="newValue">The property's value after the change
        /// occurred.</param>
        /// <param name="broadcast">If true, a PropertyChangedMessage will
        /// be broadcasted. If false, only the event will be raised.</param>
        [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate",
            Justification = "This cannot be an event")]
        protected virtual void RaisePropertyChanged<T>(string propertyName, T oldValue, T newValue, bool broadcast)
        {
            RaisePropertyChanged(propertyName);
        }

        /// <summary>
        /// Raises the PropertyChanged event if needed.
        /// </summary>
        /// <param name="propertyName">The name of the property that
        /// changed.</param>
        [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate",
            Justification = "This cannot be an event")]
        protected virtual void RaisePropertyChanged(string propertyName)
        {
            VerifyPropertyName(propertyName);

            var handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        /// <summary>
        /// Verifies that a property name exists in this ViewModel. This method
        /// can be called before the property is used, for instance before
        /// calling RaisePropertyChanged. It avoids errors when a property name
        /// is changed but some places are missed.
        /// <para>This method is only active in DEBUG mode.</para>
        /// </summary>
        /// <param name="propertyName"></param>
        [Conditional("DEBUG")]
        [DebuggerStepThrough]
        public void VerifyPropertyName(string propertyName)
        {
            var myType = this.GetType();
            if (myType.GetProperty(propertyName) == null)
            {
                throw new ArgumentException("Property not found", propertyName);
            }
        }

        #region Query Handling

        protected string query = "";

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            // reload after Tombstone
            if (State.ContainsKey("Query"))
                query = (string)State["Query"];
            if (e.Uri != null && (e.Uri.OriginalString.Contains("?") || e.Uri.OriginalString.Contains("#")))
            {
                query = e.Uri.OriginalString.Split('?', '#').Last();
            }
        }

        protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedFrom(e);
            // Tombstoning
            State["Query"] = query;
        }

        protected Dictionary<string, string> queryString = null;

        protected Dictionary<string, string> QueryString
        {
            get
            {
                if (queryString == null)
                {
                    queryString = parseQS();
                }
                return queryString;
            }
        }

        protected Dictionary<string, string> parseQS()
        {
            var result = new Dictionary<string, string>();
            var nameValueLines = query.Split('&');
            foreach (var nameValueLine in nameValueLines)
                try
                {
                    var pair = nameValueLine.Split('=');
                    if (pair.Length >= 1)
                        result.Add(pair[0], (pair.Length > 1 ? pair[1] : ""));
                }
                catch (Exception ex)
                {
                    // Eat Exceptions
                }
            return result;
        }

        #endregion Query Handling
    }
}